﻿using MyWPF.Models.Curve;
using MyWPF.Views.Others;
using Newtonsoft.Json;
using Prism.Commands;
using Prism.Mvvm;
using ScottPlot;
using ScottPlot.Plottable;
using ScottPlot.Renderable;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;

namespace MyWPF.ViewModel
{
    public class VM_CurvePage : BaseViewModel
    {
        public VM_CurvePage()
        {
            #region 事件绑定
            _loadPath = new DelegateCommand<object>(_LoadPath);
            _refreshPlot = new DelegateCommand<object>(_RefreshPlot);
            #endregion
        }

        #region 属性绑定：Json文件地址
        /// <summary>
        /// Json文件地址
        /// </summary>
        public string JsonPath
        {
            get { return _jsonPath; }
            set { SetProperty(ref _jsonPath, value); }
        }
        private string _jsonPath;
        #endregion

        #region 属性绑定：曲线信息
        private System.Windows.Controls.UserControl _curveContent;
        public System.Windows.Controls.UserControl CurveContent
        {
            get { return _curveContent; }
            set { SetProperty(ref _curveContent, value); }
        }
        #endregion

        #region 事件绑定：加载Json文件和根据Json文件加载曲线
        /// <summary>
        /// 选择Json文件，将地址显示到界面上
        /// </summary>
        private ICommand _loadPath;
        public ICommand LoadPath
        {
            get { return _loadPath; }
            set
            {
                _loadPath = value;
                OnPropertyChanged("LoadPath");
            }
        }
        private void _LoadPath(object obj)
        {
            ChartDatas = new ObservableCollection<PlotContext>();
            // 创建OpenFileDialog对象
            OpenFileDialog openFileDialog = new OpenFileDialog();

            // 设置文件选择框的标题
            openFileDialog.Title = "Select a JSON file";

            // 设置文件选择框的默认文件类型和过滤器
            openFileDialog.DefaultExt = "json";
            openFileDialog.Filter = "JSON files (*.json)|*.json|All files (*.*)|*.*";

            // 显示文件选择框
            DialogResult result = openFileDialog.ShowDialog();

            // 判断是否选择了文件
            if (result == DialogResult.OK)
            {
                // 获取选中的文件名
                JsonPath = openFileDialog.FileName;
            }
        }
        /// <summary>
        /// 将Json文件解析后显示在界面上
        /// </summary>
        private ICommand _refreshPlot;
        public ICommand RefreshPlot
        {
            get { return _refreshPlot; }
            set
            {
                _refreshPlot = value;
                OnPropertyChanged("RefreshPlot");
            }
        }
        private void _RefreshPlot(object obj)
        {
            LoadJson(JsonPath);
        }


        private void OnPropertyChanged(string v)
        {
            throw new NotImplementedException();
        }
        #endregion

        #region 属性绑定/事件：刷新ScottPlot界面数据
        /// <summary>
        /// 测试曲线用，这里添加了三条曲线
        /// </summary>
        private void Test_RefreshScottPlot()
        {
            ChartDatas = new ObservableCollection<PlotContext>();
            Random random = new Random();
            double[] array = Enumerable.Range(1, 5000).Select(x => (double)x).ToArray();
            double[] datas1 = DataGen.RandomWalk(random, 5000);
            double[] datas2 = DataGen.RandomWalk(random, 5000);
            double[] datas3 = DataGen.RandomWalk(random, 5000);
            Task.Run(() =>
            {
                DataCurve plotContext1 = new DataCurve()
                {
                    Name = "第一条曲线",
                    X = array,
                    Y = datas1,
                    SmoothTension = 0.1,
                    MarkSize = 0
                };
                DataCurve plotContext2 = new DataCurve()
                {
                    Name = "第二条曲线",
                    X = array,
                    Y = datas2,
                    SmoothTension = 0.1,
                    MarkSize = 0
                };
                DataCurve plotContext3 = new DataCurve()
                {
                    Name = "第三条曲线",
                    X = array,
                    Y = datas3,
                    SmoothTension = 0.1,
                    MarkSize = 0
                };
                List<DataCurve> dataCurves = new List<DataCurve>();
                dataCurves.Add(plotContext1);
                dataCurves.Add(plotContext2);
                dataCurves.Add(plotContext3);
                ChartDatas.Add(new PlotContext
                {
                    Name = "测试曲线2",
                    Model = Model.DataCurve,
                    DataCurves = dataCurves
                });

                //将StaticModels.staticInfo.config序列化后保存
                string configStr = JsonConvert.SerializeObject(ChartDatas.ToArray()[0]);
                var filePath = "曲线2.json";
                File.WriteAllText(filePath, configStr);
            });


        }

        private void Test_LoadJsonAndRefreshScottPlot()
        {
            LoadJson("曲线.json");
        }

        public ObservableCollection<PlotContext> ChartDatas
        {
            get { return _chartDatas; }
            set { SetProperty(ref _chartDatas, value); }
        }
        private ObservableCollection<PlotContext> _chartDatas;
        #endregion

        #region 事件：将曲线Json文件显示在界面上

        /// <summary>
        /// 将json格式曲线文件显示在界面上。输入<see cref="string"/>类型json文件路径，加载该曲线
        /// </summary>
        /// <param name="Path"></param>
        private void LoadJson(string Path)
        {
            try
            {
                //提取json文件的文本内容
                string json = File.ReadAllText(Path);
                //反序列化
                PlotContext Datas = JsonConvert.DeserializeObject<PlotContext>(json);
                //添加到曲线界面
                #region 添加到曲线界面
                ObservableCollection<PlotContext> MidChartDatas = new ObservableCollection<PlotContext>();
                MidChartDatas.Add(Datas);
                ChartDatas = MidChartDatas;
                #endregion
                //数据分析
                #region 数据分析
                CurveContent = new System.Windows.Controls.UserControl();
                //声明主容器
                StackPanel stack = new StackPanel();
                //曲线名称
                StackPanel stack1 = new StackPanel()
                {
                    Orientation = System.Windows.Controls.Orientation.Horizontal,
                };
                TextBlock textBlock1 = new TextBlock()
                {
                    Text = "标题：",
                    FontWeight = FontWeights.Bold,
                    FontSize = 18
                };
                TextBlock textBlock2 = new TextBlock()
                {
                    Text = Datas.Name,
                    FontWeight = FontWeights.Bold,
                    FontSize = 18
                };
                stack1.Children.Add(textBlock1);
                stack1.Children.Add(textBlock2);
                stack.Children.Add(stack1);
                //曲线类型
                StackPanel stack2 = new StackPanel()
                {
                    Orientation = System.Windows.Controls.Orientation.Horizontal,
                };
                TextBlock textBlock3 = new TextBlock()
                {
                    Text = "类型：",
                    FontWeight = FontWeights.Bold,
                    FontSize = 18
                };
                TextBlock textBlock4 = new TextBlock()
                {
                    Text = Datas.Model.ToString(),
                    FontWeight = FontWeights.Bold,
                    FontSize = 18
                };
                stack2.Children.Add(textBlock3);
                stack2.Children.Add(textBlock4);
                stack.Children.Add(stack2);
                //曲线分析
                StackPanel stack3 = new StackPanel()
                {
                    Margin = new Thickness(5),
                };
                switch (Datas.Model)
                {
                    case Model.Null:
                        break;
                    case Model.DataCurve:
                        foreach (DataCurve curve in Datas.DataCurves)
                        {
                            //写入曲线名称
                            #region 写入曲线名称
                            StackPanel stack_21 = new StackPanel()
                            {
                                Orientation = System.Windows.Controls.Orientation.Horizontal,
                            };
                            TextBlock textBlock_21 = new TextBlock()
                            {
                                Text = "曲线名称：",
                                FontWeight = FontWeights.Bold,
                                FontSize = 16
                            };
                            TextBlock textBlock_22 = new TextBlock()
                            {
                                Text = curve.Name,
                                FontWeight = FontWeights.Bold,
                                FontSize = 16
                            };
                            stack_21.Children.Add(textBlock_21);
                            stack_21.Children.Add(textBlock_22);
                            stack3.Children.Add(stack_21);
                            #endregion
                            //写入点数量
                            #region 写入点数量
                            StackPanel stack_22 = new StackPanel()
                            {
                                Orientation = System.Windows.Controls.Orientation.Horizontal,
                            };
                            TextBlock textBlock_23 = new TextBlock()
                            {
                                Text = "点数量：",
                                FontSize = 16
                            };
                            TextBlock textBlock_24 = new TextBlock()
                            {
                                Text = curve.X.Length.ToString(),
                                FontSize = 16
                            };
                            stack_22.Children.Add(textBlock_23);
                            stack_22.Children.Add(textBlock_24);
                            stack3.Children.Add(stack_22);
                            #endregion
                            //写入最大最小值
                            #region 写入最大最小值
                            StackPanel stack_23 = new StackPanel()
                            {
                                Orientation = System.Windows.Controls.Orientation.Horizontal,
                            };
                            TextBlock textBlock_25 = new TextBlock()
                            {
                                Text = "最大值：",
                                FontSize = 16
                            };
                            TextBlock textBlock_26 = new TextBlock()
                            {
                                Text = curve.Y.Max().ToString(),
                                Margin = new Thickness(0, 0, 10, 0),
                                FontSize = 16
                            };
                            TextBlock textBlock_27 = new TextBlock()
                            {
                                Text = "最小值：",
                                FontSize = 16
                            };
                            TextBlock textBlock_28 = new TextBlock()
                            {
                                Text = curve.Y.Min().ToString(),
                                FontSize = 16
                            };
                            stack_23.Children.Add(textBlock_25);
                            stack_23.Children.Add(textBlock_26);
                            stack_23.Children.Add(textBlock_27);
                            stack_23.Children.Add(textBlock_28);
                            stack3.Children.Add(stack_23);
                            #endregion

                        }
                        break;
                    case Model.TimeCurve:
                        break;
                    default:
                        break;
                }
                stack.Children.Add(stack3);
                //刷新控件
                CurveContent.Content = stack;
                #endregion
            }
            catch (Exception ex)
            {
                Tips tips = new Tips(ex.Message);
                tips.ShowDialog();
            }
            
        }
        #endregion
    }


    public class ScottPlotExtension
    {
        [Obsolete]
        public static ObservableCollection<PlotContext> GetValues(DependencyObject obj)
        {
            return (ObservableCollection<PlotContext>)obj.GetValue(ValuesProperty);
        }
        [Obsolete]
        public static void SetValues(DependencyObject obj, ObservableCollection<double> value)
        {
            obj.SetValue(ValuesProperty, value);
        }

        [Obsolete]
        public static readonly DependencyProperty ValuesProperty =
            DependencyProperty.RegisterAttached(
                "Values",
                typeof(ObservableCollection<PlotContext>),
                typeof(ScottPlotExtension),
                new PropertyMetadata(null, new PropertyChangedCallback(OnValuesChanged)));

        /// <summary>
        /// 数据处理
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        [Obsolete]
        private static void OnValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            #region 初始化数据
            //所有的数据都在这个datas里
            PlotContext datas;
            try
            {
                datas = (e.NewValue as ObservableCollection<PlotContext>)[0];
            }
            catch (Exception ex)
            {
                return;
            }
            //obj是界面曲线实例
            var obj = d as WpfPlot;
            //先将曲线重置用obj.plt.Clear()是不可以的，只能清空曲线，其它Y轴等不会清空。
            obj.Reset();
            #endregion
            #region 设置曲线默认样式
            //设置样式
            obj.plt.Style(
                //背景色：figureBackground
                figureBackground: Color.FromArgb(0x00, 0x6e, 0x6e, 0x6e),
                //坐标系背景色：dataBackground
                dataBackground: Color.FromArgb(0x00, 0x6e, 0x6e, 0x6e),
                //坐标系颜色：tick
                tick: Color.FromArgb(0xff, 0x6e, 0x6e, 0x6e),
                //标题颜色
                titleLabel: Color.FromArgb(0xff, 0x6e, 0x6e, 0x6e)
                );
            //设置标题
            obj.plt.Title(datas.Name != null ? datas.Name : "无标题");
            #endregion
            switch (datas.Model)
            {
                case Model.Null:
                    #region 曲线为空

                    #endregion
                    break;
                case Model.DataCurve:
                    #region 曲线为纯数据
                    for (int i = 0; i < datas.DataCurves.Count; i++)
                    {
                        //添加曲线
                        ScatterPlot Plot = obj.plt.AddScatter(datas.DataCurves[i].X, datas.DataCurves[i].Y, label: datas.DataCurves[i].Name);
                        //设置曲线属性：点大小
                        Plot.MarkerSize = datas.DataCurves[i].MarkSize;
                        //设置曲线属性：圆滑度
                        Plot.Smooth = true;
                        Plot.SmoothTension = datas.DataCurves[i].SmoothTension;
                        //添加Y轴
                        if (i == 0)
                        {
                            obj.plt.YAxis.Label(datas.DataCurves[i].Name, Color.FromArgb(0xff, 0x6e, 0x6e, 0x6e));
                            
                        }
                        else
                        {
                            var yAxis = obj.plt.AddAxis(Edge.Left);
                            yAxis.Label(datas.DataCurves[i].Name, Color.FromArgb(0xff, 0x6e, 0x6e, 0x6e));
                            Plot.YAxisIndex = yAxis.AxisIndex;
                        }
                    }
                    #endregion
                    break;
                case Model.TimeCurve:
                    #region 曲线为时间曲线
                    for (int i = 0;i < datas.TimeCurves.Count;i++)
                    {

                    }
                    #endregion
                    break;
            }
            //右下角显示曲线标识
            obj.plt.Legend();
            //界面刷新
            obj.Refresh();
        }
    }

    
}
